home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / nm.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  4KB  |  201 lines

  1. /* nm - print name list.        Author: Dick van Veen */
  2.  
  3. /* Dick van Veen: veench@cs.vu.nl */
  4.  
  5. #include <sys/types.h>
  6. #include <a.out.h>
  7. #include <fcntl.h>
  8. #include <unistd.h>
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11.  
  12. /* Read the name list in memory, sort it, and print it.  */
  13.  
  14. /* Nm [-gnopru] [file] ...
  15.  *
  16.  * flags:
  17.  *    -d    address in decimal
  18.  *    -g    print only external symbols.
  19.  *    -n    sort numerically rather than alphabetically.
  20.  *    -o    prepend file name to each line rather than only once.
  21.  *    -p    don't sort, pint n symbol-table order.
  22.  *    -r    sort in reverse order.
  23.  *    -u    print only undefined symbols.
  24.  *
  25.  *    -    when no file name is present, a.out is assumed.
  26.  *
  27.  *    NOTE:    no archives are supported because assembly files don't
  28.  *        have symbol tables.
  29.  *
  30.  */
  31.  
  32. #define A_OUT        "a.out"
  33.  
  34. int d_flag;
  35. int g_flag;
  36. int n_flag;
  37. int o_flag;
  38. int p_flag;
  39. int r_flag;
  40. int u_flag;
  41.  
  42. char io_buf[BUFSIZ];        /* io buffer */
  43. struct exec header;        /* header of a.out file */
  44. int stbl_elems;            /* #elements in symbol table */
  45.  
  46. main(argc, argv)
  47. int argc;
  48. char **argv;
  49. {
  50.   argv++;
  51.   while (*argv != 0 && **argv == '-') {
  52.     *argv += 1;
  53.     while (**argv != '\0') {
  54.         switch (**argv) {
  55.             case 'd':    d_flag = 1;    break;
  56.             case 'g':    g_flag = 1;    break;
  57.             case 'n':    n_flag = 1;    break;
  58.             case 'o':    o_flag = 1;    break;
  59.             case 'p':    p_flag = 1;    break;
  60.             case 'r':    r_flag = 1;    break;
  61.             case 'u':    u_flag = 1;    break;
  62.             default:
  63.             fprintf(stderr, "illegal flag: -%c\n", **argv);
  64.             exit(-1);
  65.         }
  66.         *argv += 1;
  67.     }
  68.     argv++;
  69.   }
  70.   setbuf(stdin, io_buf);
  71.   if (*argv == 0)
  72.     nm(A_OUT);
  73.   else
  74.     while (*argv != 0) {
  75.         nm(*argv);
  76.         argv++;
  77.     }
  78.   exit(0);
  79. }
  80.  
  81. nm_sort(stbl1, stbl2)
  82. struct nlist *stbl1, *stbl2;
  83. {
  84.   int cmp;
  85.  
  86.   if (n_flag) {            /* sort numerically */
  87.     if ((stbl1->n_sclass & N_SECT) <
  88.         (stbl2->n_sclass & N_SECT))
  89.         cmp = -1;
  90.     else if ((stbl1->n_sclass & N_SECT) >
  91.          (stbl2->n_sclass & N_SECT))
  92.         cmp = 1;
  93.     else if (stbl1->n_value < stbl2->n_value)
  94.         cmp = -1;
  95.     else if (stbl1->n_value > stbl2->n_value)
  96.         cmp = 1;
  97.     else
  98.         cmp = strncmp(stbl1->n_name, stbl2->n_name, 8);
  99.   } else {
  100.     cmp = strncmp(stbl1->n_name, stbl2->n_name, 8);
  101.     if (cmp == 0) {
  102.         if (stbl1->n_value < stbl2->n_value)
  103.             cmp = -1;
  104.         else if (stbl1->n_value > stbl2->n_value)
  105.             cmp = 1;
  106.     }
  107.   }
  108.  
  109.   if (r_flag) cmp = -cmp;    /* reverse sort */
  110.   return(cmp);
  111. }
  112.  
  113. nm(file)
  114. char *file;
  115. {
  116.   struct nlist *stbl;
  117.   int fd;
  118.  
  119.   fd = open(file, O_RDONLY);
  120.   if (fd == -1) {
  121.     fprintf(stderr, "can't open %s\n", file);
  122.     return;
  123.   }
  124.   if (read_header(fd)) {
  125.     fprintf(stderr, "%s: no executable file\n", file);
  126.     close(fd);
  127.     return;
  128.   }
  129.   if (header.a_syms != 0) {
  130.     stbl = (struct nlist *) malloc((int) (header.a_syms & 0xFFFF));
  131.     if (stbl == NULL) {
  132.     fprintf(stderr, "%s: can't allocate symbol table\n", file);
  133.     return;
  134.     }
  135.     if (read(fd, (char *) stbl, (int) (header.a_syms & 0xFFFF))
  136.         != (int) (header.a_syms & 0xFFFF)) {
  137.       fprintf(stderr, "%s: can't read symbol table\n", file);
  138.       return;
  139.     }
  140.     stbl_elems = (int) header.a_syms / sizeof(struct nlist);
  141.     if (!p_flag) qsort(stbl, stbl_elems, sizeof(struct nlist), nm_sort);
  142.     nm_print(file, stbl);
  143.     close(fd);
  144.   }
  145. }
  146.  
  147. read_header(fd)
  148. int fd;
  149. {
  150.   if (read(fd, (char *) &header, sizeof(struct exec)) != sizeof(struct exec))
  151.     return(1);
  152.   if (BADMAG(header)) return(1);
  153.   lseek(fd, A_SYMPOS(header), SEEK_SET);
  154.  
  155.   return(0);
  156. }
  157.  
  158. nm_print(file, stbl)
  159. char *file;
  160. register struct nlist *stbl;
  161. {
  162.   struct nlist *last;
  163.   char name[9];
  164.   int n_sclass;
  165.   char type;
  166.  
  167.   name[8] = '\0';
  168.   if (!o_flag) printf("%s:\n", file);
  169.   for (last = &stbl[stbl_elems]; stbl != last; stbl++) {
  170.     if (g_flag && (stbl->n_sclass & N_CLASS) != C_EXT) continue;
  171.     if (u_flag && (stbl->n_sclass & N_SECT) != N_UNDF) continue;
  172.  
  173.     n_sclass = stbl->n_sclass & N_SECT;
  174.     if (n_sclass == N_ABS)
  175.         type = 'a';
  176.     else if (n_sclass == N_TEXT)
  177.         type = 't';
  178.     else if (n_sclass == N_DATA)
  179.         type = 'd';
  180.     else if (n_sclass == N_BSS)
  181.         type = 'b';
  182.     else
  183.         type = 'u';
  184.     if ((stbl->n_sclass & N_CLASS) == C_EXT) type += 'A' - 'a';
  185.     strncpy(name, stbl->n_name, 8);
  186.     if (d_flag) {
  187.         /* Offsets in decimal. */
  188.         if (o_flag) 
  189.                printf("%s:%08ld %c %s\n",file,stbl->n_value,type,name);
  190.         else
  191.                printf("%08ld %c %s\n", stbl->n_value, type, name);
  192.     } else {
  193.         /* Offsets in hex. */
  194.         if (o_flag) 
  195.                printf("%s:%08lx %c %s\n",file,stbl->n_value,type,name);
  196.         else
  197.                printf("%08lx %c %s\n", stbl->n_value, type, name);
  198.     }
  199.   }
  200. }
  201.